package com.shiro.test.mvc.filter;

import com.shiro.test.mvc.pojo.MenuPermission;
import com.shiro.test.mvc.service.IMenuService;
import org.apache.shiro.config.Ini;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.util.CollectionUtils;
import org.apache.shiro.util.StringUtils;
import org.apache.shiro.web.filter.mgt.DefaultFilterChainManager;
import org.apache.shiro.web.filter.mgt.FilterChainManager;
import org.apache.shiro.web.filter.mgt.FilterChainResolver;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.springframework.beans.factory.annotation.Autowired;

import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * Created by Administrator on 2020/11/25 0025.
 */
public class MyShiroFilterFactoryBean extends ShiroFilterFactoryBean{

    private static final String ROLE_STRING="roles[{0}]";

    @Autowired
    private IMenuService menuService;

    /*
    该方法在系统启动时即加载预设好的用户权限信息，无法实时动态加载新的用户权限
     */
    public void setFilterChainDefinitions(String definitions) {
        Ini ini = new Ini();
        ini.load(definitions);
        Ini.Section section = ini.getSection("urls");
        if(CollectionUtils.isEmpty(section)) {
            section = ini.getSection("");
        }

        //模拟从数据库中读取的数据
//        Map<String,String[]> permsMap = new HashMap<>();
//        permsMap.put("/dotest1.html",new String[]{"test"});
//        permsMap.put("/dotest2.html",new String[]{"test","guest"});
//        permsMap.put("/dotest3.html",new String[]{"admin"});
//        for (String url:permsMap.keySet()) {
//            String[] roles = permsMap.get(url);
//            StringBuilder sb = new StringBuilder();
//            for (String role : roles) {
//                sb.append(role).append(",");
//            }
//            String str = sb.substring(0,sb.length()-1);
//            //roles[perm1,perm2]
//            section.put(url, MessageFormat.format(ROLE_STRING,str));
//        }
//        this.setFilterChainDefinitionMap(section);
        //从数据库中查询出所有的用户的权限
        List<MenuPermission> menuPermissions = menuService.getMenuPerms();
        if(menuPermissions != null){
            for (MenuPermission menuPermission : menuPermissions) {
                List<Integer> roleIds = menuPermission.getRoleIds();
                if (StringUtils.hasLength(menuPermission.getUrl())&&roleIds != null&&roleIds.size()>0){
                    StringBuilder sb = new StringBuilder();
                    for (Integer role : roleIds) {
                        sb.append(role).append(",");
                    }
                    String str = sb.substring(0,sb.length()-1);
                    //roles[perm1,perm2]
                    section.put(menuPermission.getUrl().substring(0,menuPermission.getUrl().indexOf("?")), MessageFormat.format(ROLE_STRING,str));
                }
            }
        }
        //声明除以上已经约定好的用户权限，未约定的权限，用户需要登录系统才能正常访问
        section.put("/**","authc");
        this.setFilterChainDefinitionMap(section);
    }

    /*
    此方法需主动调用，可将新加载的权限通过DefaultFilterChainManager对象，令其实时生效。
     */
    public void update(){
        synchronized (this){
           try {
               AbstractShiroFilter shiroFilter = (AbstractShiroFilter)this.getObject();
               PathMatchingFilterChainResolver resolver = (PathMatchingFilterChainResolver) shiroFilter.getFilterChainResolver();
               DefaultFilterChainManager manager = (DefaultFilterChainManager) resolver.getFilterChainManager();
               manager.getFilterChains().clear();
               this.getFilterChainDefinitionMap().clear();
               this.setFilterChainDefinitions("/dotest3.html=authc,roles[test]");

               Map<String, String> chains = this.getFilterChainDefinitionMap();
               if (CollectionUtils.isEmpty(chains)){
                   Iterator<Map.Entry<String, String>> iterator = chains.entrySet().iterator();
                   while (iterator.hasNext()){
                       Map.Entry<String, String> entry = (Map.Entry) iterator.next();
                       String url = entry.getKey();
                       String chainDefinition = entry.getValue();

                   }
               }
           } catch (Exception e) {
               e.printStackTrace();
           }
        }
    }
}
